package com.lifesting.tool.j2as3.visit;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.util.IModifierConstants;
import org.eclipse.search.ui.text.Match;

import com.lifesting.java2as3.analysis.MatchDescriptor;

public class AnalysisVisitor extends ASTVisitor {
	private CompilationUnit unit;
	private String[] rootPackages;
	private Set<MatchDescriptor> outerElements = new HashSet<MatchDescriptor>();
	@Override
	public void endVisit(CompilationUnit node) {
		unit = null;
	}
	public Match[] getOuterElements() {
		Match[] match = new Match[outerElements.size()];
		int i = 0;
		for (MatchDescriptor m : outerElements){
			match[i++] = new Match(m.getElement(),m.getStartPosition(),m.getLength());
		}
		return match;
	}
	@Override
	public boolean visit(CompilationUnit node) {
		unit = node;
		return true;
	}
	public void reset()
	{
		outerElements.clear();
	}
	public void setRootPackages(String[] rootPkg) {
		this.rootPackages = rootPkg;		
	}

	@Override
	public boolean visit(MethodInvocation node) {
		IMethodBinding binding = node.resolveMethodBinding();
		ITypeBinding tb = binding.getDeclaringClass();
		String declared_qn = tb.getQualifiedName();
		if (!includeType(declared_qn)){
			
			IJavaElement javaElement = binding.getJavaElement();
			if (javaElement == null) return false;
			outerElements.add(new MatchDescriptor(unit.getJavaElement(),node.getStartPosition(),node.getLength()));
		}
		return true;
	}
	
	@Override
	public boolean visit(FieldAccess node) {
		IVariableBinding field_binding = node.resolveFieldBinding();
		ITypeBinding iTypeBinding = field_binding.getDeclaringClass();
		if (iTypeBinding== null) return false;
		String declared_qn = iTypeBinding.getQualifiedName();
		if (!includeType(declared_qn)){
			IJavaElement javaElement = field_binding.getJavaElement();
			if(javaElement == null) return false;
			outerElements.add(new MatchDescriptor(unit.getJavaElement(),node.getStartPosition(),node.getLength()));
		}
		return false;
	}
	@Override
	public boolean visit(QualifiedName node) {
		IBinding resolveBinding = node.resolveBinding();
		if(resolveBinding == null) return false;
		if(resolveBinding.getKind() != IBinding.VARIABLE) return false;
		IVariableBinding vb = (IVariableBinding) resolveBinding;
		int modifier_flag = vb.getModifiers();
		if(!vb.isField() || (modifier_flag & IModifierConstants.ACC_STATIC) ==0) return false;
		ITypeBinding type_binging = node.resolveTypeBinding();
		if (type_binging == null) return false;
		String declared_qn = type_binging.getQualifiedName();
		if (!includeType(declared_qn)){
			
			IJavaElement javaElement = resolveBinding.getJavaElement();
			if(javaElement == null) return false;
			outerElements.add(new MatchDescriptor(unit.getJavaElement(),node.getStartPosition(),node.getLength()));
		}
		return false;
	}

	private boolean includeType(String declared_qn) {
		for (String pkg : rootPackages){
			if (declared_qn.startsWith(pkg)){
				return true;
			}
		}
		return false;
	}
	
}
